package simonxianyu.demo.shiro.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import simonxianyu.demo.shiro.util.shiro.MyFormAuthFilter;

import javax.sql.DataSource;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 *
 * Created by simon on 2017/3/4.
 */
@Configuration
public class ShiroConfig  {

  @Bean
  public RedisManager redisManager() {
    RedisManager manager = new RedisManager();
    manager.setHost("127.0.0.1");
    manager.setPort(6379);
    return manager;
  }

  @Bean
  public RedisSessionDAO sessionDAO() {
    RedisSessionDAO dao = new RedisSessionDAO();
    dao.setRedisManager(redisManager());
    return dao;
  }

  @Bean
  public RedisCacheManager redisCacheManager() {
    RedisCacheManager manager = new RedisCacheManager();
    manager.setRedisManager(redisManager());
//    manager.setKeyPrefix("shiro-session"); // modify this to use customized key name
    return manager;
  }

  @Bean("jdbcRealm")
  public JdbcRealm jdbcRealm(DataSource dataSource) {
    JdbcRealm jdbcRealm = new JdbcRealm();
    jdbcRealm.setDataSource(dataSource);
    jdbcRealm.setAuthenticationQuery(
        "SELECT password FROM sysuser WHERE loginid=?");
    jdbcRealm.setUserRolesQuery(
        "SELECT roleid FROM sysuserrole where loginid=? "
    );
    jdbcRealm.setCredentialsMatcher(new HashedCredentialsMatcher("MD5"));
    return jdbcRealm;
  }

  @Bean
  public DefaultWebSessionManager defaultWebSessionManager() {
    DefaultWebSessionManager manager = new DefaultWebSessionManager();
    SimpleCookie cookie = new SimpleCookie("SPRING_SHIRO"); // configure cookie name
    manager.setSessionIdCookie(cookie);
    // use redis
    manager.setSessionDAO(sessionDAO());

    return manager;
  }

  @Bean
  public DefaultWebSecurityManager defaultWebSecurityManager(Realm realm) {
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    manager.setSessionManager(defaultWebSessionManager());
    manager.setRealm(realm);
    // Use redis
    manager.setCacheManager(redisCacheManager());
    return manager;
  }

  @Bean(name="shiroFilter")
  public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
    bean.setSecurityManager(securityManager);
    bean.setSuccessUrl("/dashboard");
    bean.setLoginUrl("/loginform");
    Map<String, String> filterChainMap = new LinkedHashMap<>();
    filterChainMap.put("/static/**", "anon");
    filterChainMap.put("/logout", "logout");
    filterChainMap.put("/**", "authc");
    bean.setFilterChainDefinitionMap(filterChainMap);
    return bean;
  }

  @Bean(name="anon")
  public AnonymousFilter anonymousFilter() {
    return new AnonymousFilter();
  }
  @Bean(name="authc")
  public FormAuthenticationFilter authenticationFilter() {
    return new MyFormAuthFilter();
  }
  @Bean(name="logout")
  public LogoutFilter logoutFilter() {
    return new LogoutFilter();
  }

  @Bean
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }
}
